package com.ror.game;

import com.ror.domain.Player;
import com.ror.domain.Poker;
import com.ror.domain.Seat;
import com.ror.event.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

//1名地主(17张手牌+3张底牌)和2名农民(17张手牌)
public class PokerGame {
    //所有牌的唯一标识数
    private static final ArrayList<Integer> cardIndexes = new ArrayList<>();

    static {
        //初始化唯一标识数
        Poker.getCards().forEach(card -> cardIndexes.add(card.getIndex()));
    }

    //别的类在此注册成为本类的观察者
    //本类发生事件时，它会通知所有注册的观察者，它们将执行各自实现的观察者响应逻辑
    private final List<GameObserver> observers = new ArrayList<>();

    public PokerGame(GameObserver observer) {
        this.addObserver(observer);
    }

    //初始化一局游戏
    public void initGame() {
        Player.initPlayers();
        shuffleCards();
        distributeCards();
        sortEveryoneCards();
        showEveryoneCards();
    }

    //洗牌
    public void shuffleCards() {
        Collections.shuffle(cardIndexes);
    }

    //发牌
    public void distributeCards() {
        for (int i = 0; i < cardIndexes.size(); i++) {
            //取牌
            Poker card = Poker.cardOf(cardIndexes.get(i));
            //选席
            Seat seat;
            if (i < 51) { //坐人席
                //按余数决定发牌席位，实现轮席发牌
                seat = Seat.occupiedSeats.get(i % Seat.occupiedSeats.size());
            } else { //底牌席，3张底牌
                seat = Seat.HAND;
            }
            //发牌
            seat.addCard(card);
            //通知界面更新
            notifyObservers(GameEventType.CARD_DISTRIBUTED,
                    new CardDistributedEventArgs(card, seat));
        }
    }

    //让所有玩家理牌
    public void sortEveryoneCards() {
        Player.sortAll();
    }

    //打印每名玩家的手牌
    public void showEveryoneCards() {
        Player.PLAYERS.forEach(System.out::println);
    }

    //给其他类调用，注册=成为本类的观察者
    public void addObserver(GameObserver observer) {
        observers.add(observer);
    }

    //给其他类调用，注销=不再为本类的观察者
    public void removeObserver(GameObserver observer) {
        observers.remove(observer);
    }

    //仅供本类和它的子类调用，通知所有注册的观察者
    protected void notifyObservers(GameEventType eventType, GameEventArgs eventArgs) {
        GameEvent e = new GameEvent(eventType, eventArgs);
        observers.forEach(o -> o.onGameUpdated(e));
    }
}
